package cn.tedu.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author :Colin
 * @version 创建时间: 2021/6/24 14:05
 * 本类用于测试自定义注解，熟悉注解相关的规则
 */
public class TestAnnotation {}

    /*0.首先注意：自定义注解的语法与java的不同，不要套用java的格式*/
    /*1.注解定义要使用“@interface 注解名”的方式来定义*/
    /*1.1需要通过@Target注解来描述当前自定义注解可以使用的位置
    * 注意@Target注解使用时需要导包，它的值通过ElementType.静态常量来指定
    * 如果需要指定多个值，可以用{，}的格式来写（数组形式）*/
    //@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE})
    @Target({ElementType.METHOD,ElementType.FIELD})
    /*1.2我们通过@Retention注解表明此自定义注解的生命周期
    * 注意@Retention使用时也需要导包
    * 他的值通过“retention policy.静态常来”来指定
    * 也就是自定义注解可以存活多久，源文件中/字节码文件中/运行时
    * 而且，这三个值只能选一个，不能写多个*/
    @Retention(RetentionPolicy.SOURCE)
    @interface Test{
            /*3.自定义注解可以添加功能--给自定义注解添加属性
            *注意：int age（）；不是方法的定义，而是自定义注解中定义age属性的语法*/
        /*3.1如果为了使用时方便，还可以给属性指定默认值，这样的注解就可以不复制直接使用
        *int age（） default 0；*/

        int age() default 0;
        //给注解定义一个特殊属性value
        String value() default "lemon";}
        /*注解中还可以添加功能，可以定义特殊属性value
        * 特殊属性的定义于其他普通属性的定义相同，主要是使用方式不同
        * 使用此注解时，属性赋值不在需要写属性名，直接写值就可以
        * 也就是说@test（value=“apple”）可以简写@Test（“apple”）
        * 但是自定义注解的特殊属性赋予默认值时的格式不能简写
        * 如果给特殊属性赋予了默认值，使用时可以不赋值，使用默认值即可
        *
         */



    /*2.使用注解时，只要在自定义注解前加@符号即可使用此注解*/

class TestAnno{
        /*测试1：分别给TestAnno类/name属性/eat方法都添加了@Test注解，只有方法和属性上不报错*/
        /*结论：自定义注解能够加载什么位置上，取决于Target注解的值
        * 测试2：修改@Target注解的值：
        *     @Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE})
         结果：注解@Test可以存在于多个位置，如果有多个值，格式为{，}*/
        /*原因：Target注解的源码：ElementType【】 value（）；*/
//            @Test
            String name;
            /*测试3：当我们添加了注解的age属性后，@test注解报错
            *结论当没有给自定义注解定义属性时，可以直接使用，但是如果有属性了，必须给属性赋值
            *测试4：给@Test注解的属性赋值以后，就不报错了
            * 结论：给属性复制的格式“@Test（age=18）”，注意不给你直接写值，这是错误的格式
            * 测试5：给age属性赋值值后，可以不加属性值直接使用注解，此时使用的属性值时age的默认值*/

//            @Test(age = 18)
        /*测试6：给特殊属性value赋值时可以简写，相当于value=“apple”*/
        @Test("apple")
            //@Test(value ="apple")
        /*测试7：因为两个属性均被设置默认值，所以无需赋值，可以使用@Test注解*/
            public void eat(){
                System.out.println("点个奶茶吧，加冰激凌和催伯伯");
            }
 }

